home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / util / cdity / yak158src.lha / handler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-22  |  22.4 KB  |  563 lines

  1. /*
  2.  * handler.c
  3.  *
  4.  * Routines to set up handler.
  5.  * Part of Yak.
  6.  *
  7.  * Martin W. Scott, 9/92.
  8.  */
  9. #include <exec/types.h>
  10. #include <exec/exec.h>
  11. #include <hardware/custom.h>
  12. #include <hardware/dmabits.h>
  13. #include <devices/console.h>
  14. #include <devices/input.h>
  15. #include <devices/inputevent.h>
  16. #include <libraries/commodities.h>
  17. #include <graphics/gfxbase.h>
  18. #include <graphics/gfxmacros.h>
  19. #include <graphics/displayinfo.h>
  20. #include <intuition/intuition.h>
  21. #include <intuition/intuitionbase.h>
  22. #include <proto/exec.h>
  23. #include <proto/dos.h>
  24. #include <proto/layers.h>
  25. #include <proto/graphics.h>
  26. #include <proto/intuition.h>
  27. #include <proto/commodities.h>
  28. #include <string.h>
  29.  
  30. #include "code.h"
  31. #include "yak.h"
  32. #include "beep.h"
  33.  
  34.  
  35. void TurnMouseOn (void);
  36. static void TurnMouseOff (void);
  37. static __regargs void IntuiOp (void (*routine) (APTR), APTR parameter);
  38. static __regargs void PopToFront (struct Window *win);
  39. static struct Window *WindowUnderMouse (void);
  40. static __regargs BOOL StrGadgetActive (struct Window *w);
  41.  
  42. extern __far struct Custom custom;
  43.  
  44. #define REBLANKCOUNT    10      /* how long to wait to reblank mouse */
  45.  
  46. void (*intui_routine) (APTR);   /* for intui_op's */
  47. APTR intui_parameter;
  48. CxObj *clickobj;
  49. ULONG clicksigflag, intuiopsigflag;
  50. static BYTE clicksigbit, intuiopsigbit = -1;
  51. static struct Task *thistask;
  52. static BOOL misspop;
  53.  
  54.  
  55. /* for screen click-to-back */
  56. STACKARGS void
  57. MyScreenToBack (struct Screen *scr)
  58. {
  59.   ScreenToBack (scr);
  60.   ActivateMouseWindow (SCREEN);
  61. }
  62.  
  63.  
  64. /* Stub for Intuition routines - passes request on to main task.
  65.  * DO NOT CALL WHILE FORBID()ING!
  66.  
  67.  * Thanks to Eddy Carroll for this.
  68.  */
  69.  
  70. #define WTB(win)        IntuiOp(WindowToBack, win)
  71. #define WTF(win)        IntuiOp(WindowToFront, win)
  72. #define WACT(win)       IntuiOp((void (*)(APTR))ActivateWindow, win)
  73. #define STB(scr)        IntuiOp(MyScreenToBack, scr)
  74. #define STF(scr)        IntuiOp(ScreenToFront, scr)
  75.  
  76. static __regargs void
  77. IntuiOp (void (*routine) (APTR), APTR parameter)
  78. {
  79.   BYTE oldpri = SetTaskPri (thistask, 21);
  80.  
  81.   intui_routine = routine;
  82.   intui_parameter = parameter;
  83.   Signal (thistask, intuiopsigflag);
  84.   SetTaskPri (thistask, oldpri);
  85. }
  86.  
  87. /* pattern-matching on screen/window titles */
  88. #define IsXXXScreen(scr, pat)  (scr && (!scr->DefaultTitle || MatchPattern(pat, scr->DefaultTitle)))
  89. #define IsClickScreen(scr)         IsXXXScreen(scr, clickscrpat)
  90. #define IsAutoScreen(scr)          IsXXXScreen(scr, autoscrpat)
  91. #define IsXXXWindow(win, pat)  (!win->Title || MatchPattern(pat, win->Title))
  92. #define IsPopWindow(win)           IsXXXWindow(win,popwinpat)
  93. #define IsClickWindow(win)         IsXXXWindow(win,clickwinpat)
  94.  
  95.  
  96. /* when is a window safe to bring to front and not already at front? */
  97. #define OkayToPop(win)  (!win->ReqCount && !(win->Flags & (WFLG_MENUSTATE|WFLG_BACKDROP)) \
  98.                          && win->WLayer->ClipRect && win->WLayer->ClipRect->Next)
  99.  
  100.  
  101. /* WindowToFront only if no requester, not backdrop, not already front... */
  102. static __regargs void
  103. PopToFront (struct Window *win)
  104. {
  105.   /* want to avoid popping immediately after mousebutton/keyboard */
  106.   if (misspop)
  107.     misspop = FALSE;
  108.   else if (OkayToPop (win))
  109.     {
  110.       /* Does it pass pattern? */
  111.       if (IsPopWindow (win))
  112.                   WTF (win);
  113.     }
  114. }
  115.  
  116. /* modified from DMouse */
  117. /* expects multitasking to be Forbid()en */
  118.  
  119. static struct Screen *mousescr; /* the screen under the mouse */
  120.  
  121.  
  122. struct Screen
  123. *ScreenUnderMouse( void )
  124. {
  125.   struct Screen *scr;
  126.   ULONG lock;
  127.  
  128.   lock = LockIBase(0);
  129.         
  130.   for (scr = FS;
  131.            scr && scr->TopEdge > 0 && scr->MouseY < 0; 
  132.            scr = scr->NextScreen);
  133.  
  134.   UnlockIBase(lock);
  135.  
  136.   return(scr);
  137. }
  138.  
  139.  
  140. static struct Window 
  141. *WindowUnderMouse( void )
  142. {
  143.   struct Layer *layer = NULL;
  144.   ULONG lock;
  145.  
  146.   lock = LockIBase(0);
  147.         
  148.   for (mousescr = FS;
  149.            mousescr && mousescr->TopEdge > 0 && mousescr->MouseY < 0; 
  150.            mousescr = mousescr->NextScreen);
  151.  
  152.   if (mousescr)
  153.           layer = WhichLayer(&mousescr->LayerInfo, mousescr->MouseX, mousescr->MouseY);
  154.  
  155.   UnlockIBase(lock);
  156.  
  157.   return (layer ? (struct Window *) layer->Window : NULL);
  158. }
  159.  
  160.  
  161. /* does active window have an active string gadget? */
  162. static __regargs BOOL
  163. StrGadgetActive (struct Window *w)
  164. {
  165.   struct Gadget *g = w->FirstGadget;
  166.  
  167.   for (; g; g = g->NextGadget)
  168.     if ((g->GadgetType & STRGADGET) && (g->Flags & GFLG_SELECTED))
  169.       return TRUE;
  170.   return FALSE;
  171. }
  172.  
  173. /* activate window under mouse */
  174. /* context sensitive; why tells routine how to behave */
  175. /* can be AUTO, KEY, SCREEN, RMBACT */
  176. __regargs void
  177. ActivateMouseWindow (BYTE why)
  178. {
  179.         struct Window *win;
  180.         BOOL forbidden = TRUE;
  181.  
  182.         Forbid ();
  183.  
  184.         if (win = WindowUnderMouse ()) /* window exists to activate */
  185.         {
  186.                 /* either window is not active or auto-activating - need to pop? */
  187.           
  188.                 if (win->Flags & WFLG_WINDOWACTIVE)     /* already active - needs popped? */
  189.                 {
  190.                         if (why == AUTO && autopop && IsAutoScreen (win->WScreen))
  191.                         {
  192.                                 Permit (), forbidden = FALSE;
  193.                                 PopToFront (win);
  194.                         }
  195.                 }
  196.                 else if (why != AUTO || IsAutoScreen (win->WScreen))
  197.                 {
  198.                         /* window is not active, should we try to activate it? */
  199.                   
  200.                         /* AW is IntuitionBase->ActiveWindow */
  201.                         if (!AW ||
  202.                                 !(AW->Flags & WFLG_MENUSTATE) && /* not showing menus */
  203.                                 !(why == KEY && StrGadgetActive (AW))) /* no str gad active */
  204.                         {
  205.                                 /* finally... */
  206.                                 Permit (), forbidden = FALSE;
  207.                           
  208.                                 /* do autopop? */
  209.                                 if (why == AUTO && autopop)
  210.                                         PopToFront (win);
  211.                           
  212.                                 if (why == KEY)
  213.                                         ActivateWindow (win); /* need this to avoid losing keys */
  214.                                 else
  215.                                         WACT (win);     /* ...activate window */
  216.                         }
  217.                 }
  218.         }
  219.         else
  220.                 /* no window under mouse... */
  221.                 {
  222.                         if (scractivate && mousescr && mousescr->FirstWindow &&
  223.                                 ((why == SCREEN) || (why == RMBACT && AW && AWS != mousescr)))
  224.                         {
  225.                                 Permit (), forbidden = FALSE;
  226.                                 WACT (mousescr->FirstWindow); /* ...activate window */
  227.                         }
  228.                 }
  229.         if (forbidden)
  230.                         Permit ();
  231. }
  232.  
  233. static __chip UWORD posctldata[4];
  234. static struct SimpleSprite simplesprite =
  235. {posctldata, 0, 0, 0, 0};
  236. static BOOL mouseoff;           /* is mouse off? (MB_SPRITES only) */
  237.  
  238. void 
  239. TurnMouseOn ()                  /* restore mouse-pointer */
  240. {
  241.         if (mouseblank == MB_SPRITES) /* really dirty blanking */
  242.     {                                                   /* but guaranteed to work... */
  243.                 if (mouseoff)
  244.                 {
  245.                         Forbid ();
  246.                         WaitTOF ();
  247.                         ON_SPRITE;
  248.                         Permit ();
  249.                 }
  250.     }
  251.         /* else using FreeSprite solution - unblanks when needed */
  252.         mouseoff = FALSE;
  253. }
  254.  
  255. static void 
  256. TurnMouseOff ()                 /* blank mouse-pointer */
  257. {
  258.         if (!mouseoff)                          /* no point in turning it off twice... */
  259.     {
  260.                 Forbid ();
  261.  
  262.                 if (mouseblank == MB_SPRITES)
  263.                 {
  264.                         WaitTOF ();
  265.                         OFF_SPRITE;
  266.                         custom.spr[0].dataa = custom.spr[0].datab = 0;          }
  267.                 else
  268.                 {
  269.                         FreeSprite (0);
  270.                         GetSprite (&simplesprite, 0);
  271.                 }
  272.  
  273.                 Permit ();
  274.  
  275.                 mouseoff = TRUE;
  276.     }
  277. }
  278.  
  279. static BOOL blanked;
  280. static struct Screen *blankscr;
  281.  
  282. /* blank display, by putting up a black screen */
  283. /* this screen's displaymode is cloned from front screen */
  284. void
  285. BlankScreen ()
  286. {
  287.         ULONG modeid = INVALID_ID;
  288.         
  289.         if (blankscr)
  290.                 ScreenToFront (blankscr);
  291.         else
  292.     {
  293.                 Forbid ();
  294.                 if (FS)
  295.                         modeid = GetVPModeID (&(FS->ViewPort));
  296.                 Permit ();
  297.                 if (modeid == INVALID_ID)
  298.                         modeid = LORES_KEY;
  299.                 
  300.                 if (blankscr = OpenScreenTags (NULL, SA_Depth, 1,
  301.                                                                            SA_Quiet, TRUE,
  302.                                                                            SA_Behind, TRUE,
  303.                                                                            SA_DisplayID, modeid,
  304.                                                                            TAG_DONE))
  305.                 {
  306.                         SetRGB4 (&blankscr->ViewPort, 0, 0, 0, 0);
  307.                         ScreenToFront (blankscr);
  308.                         blanked = TRUE;
  309.                 }
  310.     }
  311.         OFF_SPRITE;
  312.         custom.spr[0].dataa = custom.spr[0].datab = 0;
  313. }
  314.  
  315. /* unblank display, i.e. close our screen */
  316. void
  317. UnBlankScreen ()
  318. {
  319.   if (blankscr)
  320.           CloseScreen (blankscr);
  321.   blankscr = NULL;
  322.   blanked = FALSE;
  323.   ON_SPRITE;
  324. }
  325.  
  326. #define ALL_BUTTONS     (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON)
  327. #define KEY_QUAL        (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT \
  328.                         |IEQUALIFIER_CONTROL \
  329.                         |IEQUALIFIER_LALT|IEQUALIFIER_RALT \
  330.                         |IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND)
  331. #define ALL_QUALS       (ALL_BUTTONS|KEY_QUAL)
  332.  
  333. /* the input handler itself */
  334. SAVEDS void
  335. Handler (CxMsg * CxMsg, CxObj * CO)
  336. {
  337.         static struct timeval lastclick; /* last left-button click */
  338.         static WORD apcount;            /* timer events since last mousemove */
  339.         struct InputEvent *ev;
  340.         
  341.         ev = (struct InputEvent *) CxMsgData (CxMsg);
  342.         
  343.         if (ev->ie_Class == IECLASS_TIMER)
  344.     {
  345.                 /*** AUTO-ACTIVATE/POP, SCREENBLANK, MOUSEBLANK ***/
  346.                 if (!(ev->ie_Qualifier & ALL_QUALS) && autopoint && !apcount--)
  347.                 {
  348.                         ActivateMouseWindow (AUTO);
  349.                 }
  350.                 
  351.                 if (blanktimeout && !--blankcount) /* blank screen? */
  352.                 {
  353.                         BlankScreen ();
  354.                         blankcount = blanktimeout; /* reset counter */
  355.                 }                                               /* in case sceen opens on top */
  356.                 
  357.                 if (mouseblank && !--mblankcount) /* blank mouse? */
  358.                 {
  359.                         mouseoff = FALSE;       /* force reblank */
  360.                         TurnMouseOff ();
  361.                         /* in case someone else turns it on, reset counter */
  362.                         mblankcount = REBLANKCOUNT;
  363.                 }
  364.     }
  365.         else 
  366.                 if ((ev->ie_Class == IECLASS_RAWKEY) && !(ev->ie_Code & IECODE_UP_PREFIX))
  367.                 {
  368.                         /*** MOUSEBLANK, KEYACTIVATE, KEYCLICK ***/
  369.                         
  370.                         blankcount = blanktimeout; /* reset blanking countdown */
  371.                         if (blanked)            /* turn off screen-blanking */
  372.                                 UnBlankScreen ();
  373.                         
  374.                         if (mouseblank)
  375.                                 if (ev->ie_Qualifier & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND))
  376.                                 {
  377.                                         /* this allows use of keyboard to move mouse and to access menus */
  378.                                         mblankcount = mblanktimeout;
  379.                                         TurnMouseOn ();
  380.                                 }
  381.                                 else
  382.                                 {
  383.                                         if (blankmouseonkey)
  384.                                         {
  385.                                                 TurnMouseOff (); /* blank the mouse */
  386.                                         }
  387.                                 }
  388.                         if (click_volume)
  389.                                 Signal (thistask, clicksigflag);
  390.                         
  391.                         if (keyactivate)        /* perform key-activate */
  392.                                 ActivateMouseWindow (KEY);
  393.                 }
  394.                 else if (ev->ie_Class == IECLASS_RAWMOUSE)
  395.                 {
  396.                         /*** CLICKTOFRONT/BACK, AUTOACTIVATE ***/
  397.                         
  398.                         /* restore screen/mouse pointer */
  399.                         blankcount = blanktimeout; /* reset blanking countdowns */
  400.                         mblankcount = mblanktimeout;
  401.                         if (blanked)            /* turn off screen-blanking */
  402.                                 UnBlankScreen ();
  403.                         if (mouseoff)
  404.                                 TurnMouseOn (); /* not needed for MB_COPPER */
  405.                         
  406.                         /* window/screen cycling... */
  407.                         /* maybe should check for depth gadgets? nah... */
  408.                         if (!(ev->ie_Qualifier & KEY_QUAL))
  409.                         {
  410.                                 if (!(ev->ie_Qualifier & ALL_BUTTONS))
  411.                                 {
  412.                                         apcount = autopoint_delay; /* reset auto-activate count */
  413.                                 }
  414.                                 else
  415.                                         /* a button - check out clicktofront etc. */
  416.                                 {
  417.                                         /* mustn't be Forbid()en when calling window op */
  418.                                         BOOL forbidden = TRUE;
  419.  
  420.                                         Forbid ();
  421.  
  422.                                         misspop = TRUE;
  423.                                         apcount = -1; /* button - wait for move */
  424.  
  425.                                         if (clicktofront && ev->ie_Code == IECODE_LBUTTON)
  426.                                         {
  427.                                                 if (DoubleClick (lastclick.tv_secs,
  428.                                                                                  lastclick.tv_micro,
  429.                                                                                  ev->ie_TimeStamp.tv_secs,
  430.                                                                                  ev->ie_TimeStamp.tv_micro))
  431.                                                 {
  432.                                                         
  433.                                                         struct Window *win = WindowUnderMouse ();
  434.  
  435.                                                         if (win)
  436.                                                         {
  437.                                                                 Permit (), forbidden = FALSE;
  438.                                                                 mousescr = win->WScreen;
  439.                                                                 
  440.                                                                 if (IsClickScreen ( mousescr ))
  441.                                                                 {
  442.                                                                         if (!(win->Flags & WFLG_BACKDROP) 
  443.                                                                                 && IsClickWindow (win) && OkayToPop (win))
  444.                                                                         {
  445.                                                                                 WTF (win); /* musn't be Forbid()en here */
  446.                                                                         }
  447.                                                                         else 
  448.                                                                                 if (screencycle)
  449.                                                                                 {
  450.                                                                                         STF (mousescr); /* musn't be Forbid()en here */
  451.                                                                                 }
  452.                                                                 }
  453.                                                         }
  454.                                                         else 
  455.                                                         {
  456.                                                                 mousescr = ScreenUnderMouse();
  457.                                                                 Permit (), forbidden = FALSE;
  458.                                                                 if (IsClickScreen ( mousescr ) && screencycle)
  459.                                                                 {
  460.                                                                         STF (mousescr); /* musn't be Forbid()en here */
  461.                                                                 }
  462.                                                         }
  463.                                                         lastclick.tv_secs = 0;
  464.                                                         lastclick.tv_micro = 0;
  465.                                                 }
  466.                                                 else
  467.                                                 {
  468.                                                         lastclick.tv_secs = ev->ie_TimeStamp.tv_secs;
  469.                                                         lastclick.tv_micro = ev->ie_TimeStamp.tv_micro;
  470.                                                 }
  471.                                         }
  472.                                         else 
  473.                                                 if (ev->ie_Code == IECODE_RBUTTON && 
  474.                                                         (ev->ie_Qualifier & IEQUALIFIER_LEFTBUTTON))
  475.                                                 {
  476.                                                         struct Window *win = WindowUnderMouse ();
  477.  
  478.                                                         if (win)
  479.                                                         {
  480.                                                                 Permit (), forbidden = FALSE;
  481.                                                                 mousescr = win->WScreen;
  482.                                                                 if (IsClickScreen ( mousescr ))
  483.                                                                 {
  484.                                                                         if (!(win->Flags & WFLG_BACKDROP) 
  485.                                                                                 && (win->NextWindow || win->WScreen->FirstWindow != win))
  486.                                                                         {
  487.                                                                                 WTB(win); /* musn't be Forbid()en here */
  488.                                                                         }
  489.                                                                         else 
  490.                                                                                 if (screencycle)
  491.                                                                                 {
  492.                                                                                         STB (mousescr); /* musn't be Forbid()en here */
  493.                                                                                 }
  494.                                                                 }       
  495.                                                         }
  496.                                                         else 
  497.                                                         {
  498.                                                                 mousescr = ScreenUnderMouse();
  499.                                                                 Permit (), forbidden = FALSE;
  500.                                                                 if (IsClickScreen ( mousescr ) && screencycle)
  501.                                                                 {
  502.                                                                         ev->ie_Class = IECLASS_NULL;
  503.                                                                         STB (mousescr);
  504.                                                                 }
  505.                                                         }
  506.                                                 }
  507.                                                 else 
  508.                                                         if ((rmbactivate && (ev->ie_Code == IECODE_RBUTTON)) || 
  509.                                                                 (mmbactivate && (ev->ie_Code == IECODE_MBUTTON)))
  510.                                                         {
  511.                                                                 Permit (), forbidden = FALSE;
  512.                                                                 ActivateMouseWindow (RMBACT);
  513.                                                         }
  514.                                                 if (forbidden)
  515.                                                         Permit ();
  516.                                         }
  517.                                 }
  518.                 }
  519.                 else 
  520.                         if (ev->ie_Class == IECLASS_DISKINSERTED)
  521.                         {
  522.                                 blankcount = blanktimeout; /* reset blanking countdown */
  523.                                 if (blanked)            /* turn off screen-blanking */
  524.                                         UnBlankScreen ();
  525.                         }
  526. }
  527.  
  528. /* close resources allocated for handler */
  529. void
  530. EndHandler ()
  531. {
  532.   if (clickobj)
  533.     DeleteCxObj (clickobj);
  534.   FreeAudio ();
  535.   if (intuiopsigbit != -1)
  536.     FreeSignal (intuiopsigbit);
  537.   if (clicksigbit != -1)
  538.     FreeSignal (clicksigbit);
  539.   UnBlankScreen ();
  540.   TurnMouseOn ();
  541. }
  542.  
  543. /* open resources needed for handler */
  544. BOOL
  545. InitHandler ()
  546. {
  547.   if (((clicksigbit = AllocSignal (-1)) != -1) &&
  548.       ((intuiopsigbit = AllocSignal (-1)) != -1) &&
  549.       AllocAudio ())
  550.     {
  551.       thistask = FindTask (NULL);       /* initialize liason structure */
  552.       clicksigflag = 1 << clicksigbit;
  553.       intuiopsigflag = 1 << intuiopsigbit;
  554.  
  555.       clickobj = CxCustom (Handler, 0L);
  556.       AttachCxObj (broker, clickobj);
  557.       return TRUE;
  558.     }
  559.   EndHandler ();
  560.   return FALSE;
  561. }
  562.  
  563.